package com.eastfair.venueservice.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.exception.BizException;
import com.eastfair.projectcore.enumeration.MenuAffiliationEnum;
import com.eastfair.venueservice.dto.ExhibitionSettlementDTO;
import com.eastfair.venueservice.dto.ServiceOrderDTO;
import com.eastfair.venueservice.entity.ServiceOrder;
import com.eastfair.venueservice.enumeration.ServiceOrderOrderSourceEnum;
import com.eastfair.venueservice.enumeration.ServiceOrderOrderStatusEnum;
import com.eastfair.venueservice.enumeration.ServiceOrderWorkOrderStatusEnum;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.ExhibitionSettlementVO;
import com.eastfair.venueservice.vo.ServiceOrderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;

/**
 * 主场报修订单 service.
 *
 * @author dqq
 * @date 2023 /4/26
 */
@Service
@Slf4j
public class HomeRepairServiceOrderServiceImpl implements HomeRepairServiceOrderService {

    @Resource
    private HomeServiceOrderService homeServiceOrderService;

    @Resource
    private ServiceOrderService serviceOrderService;

    @Resource
    private ServiceBookingService serviceBookingService;

    @Resource
    private VenueManageBuilderRepairReportService venueManageBuilderRepairReportService;

    @Override
    public List<ServiceOrderVO> listForHomeRepairOrderSettlement(ServiceOrderDTO query) {
        log.info("listForHomeRepairOrderSettlement - 查询需结算的主场报修订单, query={}", query);
        QueryWrapper<ServiceOrder> queryWrapper = createHomeSettlementQueryWrapper(query);
        List<ServiceOrder> serviceOrderList = serviceOrderService.list(queryWrapper);
        if (serviceOrderList == null || serviceOrderList.isEmpty()) {
            return Collections.emptyList();
        }
        return serviceOrderService.packageServiceBookingList(serviceOrderList);
    }

    @Override
    public ExhibitionSettlementVO getHomeRepairSettlement(ExhibitionSettlementDTO query) {
        ServiceOrderDTO orderQuery = new ServiceOrderDTO();
        orderQuery.setExhibitionManageId(query.getExhibitionManageId());
        orderQuery.setCompanyId(query.getCompanyId());
        orderQuery.setSpaceCode(query.getSpaceCode());
        orderQuery.setSpaceName(query.getSpaceName());
        orderQuery.setSiteName(query.getSiteName());
        List<ServiceOrderVO> serviceOrderList = listForHomeRepairOrderSettlement(orderQuery);
        if (serviceOrderList == null || serviceOrderList.isEmpty()) {
            return null;
        }
        ExhibitionSettlementVO exhibitionSettlementVO = ServiceOrderService.calculateExhibitionSettlement(serviceOrderList);
        return exhibitionSettlementVO;
    }

    @Override
    public ServiceOrderVO getVOByOrderNumber(String orderNumber) {
        return homeServiceOrderService.getVOByOrderNumber(orderNumber);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrder saveServiceOrderForBuilder(ServiceOrderDTO serviceOrderDTO) {
        // 校验报修单是否生成了订单
        ServiceOrder existsServiceOder = serviceOrderService.getByRepairReportNumber(serviceOrderDTO.getRepairReportNumber(), ServiceOrderOrderSourceEnum.HOME_BUILDER_REPAIR_ORDER);
        if (existsServiceOder != null && !ServiceOrderOrderStatusEnum.CANCEL.eq(existsServiceOder.getOrderStatus())) {
            throw BizException.wrap(VenueServiceExceptionCode.REPAIR_CAN_NOT_CREATE_ORDER.getCode(), "报修已预定服务，不可再预定");
        }
        serviceOrderDTO.setOrderSource(ServiceOrderOrderSourceEnum.HOME_BUILDER_REPAIR_ORDER);
        serviceOrderDTO.setBelongSystem(MenuAffiliationEnum.P_COMPOSITE_COURT.getCode());
        ServiceOrder serviceOrder = homeServiceOrderService.saveServiceOrderForBuilder(serviceOrderDTO);
        venueManageBuilderRepairReportService.updateIsBookService(serviceOrderDTO.getRepairReportNumber(), BusinessConstant.YES);
        return serviceOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrder updateServiceOrder(ServiceOrderDTO serviceOrderDTO) {
        return homeServiceOrderService.updateServiceOrder(serviceOrderDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitServiceOrder(String orderNumber) {
        homeServiceOrderService.submitServiceOrder(orderNumber);
        // 主场为搭建商下的报修订单，不需要手动报馆，所以将订单状态改为已报馆
        homeServiceOrderService.updateOrderStatusHasReportVenue(orderNumber);
        // 不需要派工，将派工状态改为已完成
        updateWorkOrderStatusComplete(orderNumber);
        // 更新报修单为已预定服务
        updateRepairReportIsBookService(orderNumber, BusinessConstant.YES);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitServiceOrder(List<String> orderNumberList) {
        if (orderNumberList == null || orderNumberList.isEmpty()) {
            return false;
        }
        orderNumberList.forEach(this::submitServiceOrder);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWorkOrderStatusComplete(String orderNumber) {
        ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(orderNumber);
        if (serviceOrder == null) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_NOT_EXIST.getCode(), "订单不存在");
        }
        // 更新订单派工状态为已完成
        serviceOrder.setWorkOrderStatus(ServiceOrderWorkOrderStatusEnum.COMPLETE);
        serviceOrderService.updateById(serviceOrder);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateRepairReportIsBookService(String orderNumber, Integer isBookService) {
        log.info("updateRepairReportIsBookService - 更新报修单是否预定服务, orderNumber={}, isBookService={}", orderNumber, isBookService);
        ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(orderNumber);
        if (serviceOrder == null) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_NOT_EXIST.getCode(), "订单不存在");
        }
        String repairReportNumber = serviceOrder.getRepairReportNumber();
        venueManageBuilderRepairReportService.updateIsBookService(repairReportNumber, isBookService);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelServiceOrder(String orderNumber) {
        homeServiceOrderService.cancelServiceOrder(orderNumber);
        // 更新报修单为为未预定服务
        updateRepairReportIsBookService(orderNumber, BusinessConstant.NO);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public boolean cancelTimeoutNotPayServiceOrder(String orderNumber) {
        return cancelServiceOrder(orderNumber);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean payServiceOrder(ServiceOrderDTO serviceOrderDTO) {
        return homeServiceOrderService.payServiceOrder(serviceOrderDTO);
    }

    /**
     * 主场报修订单待结算查询.
     *
     * @param query the query
     * @return the query wrapper
     */
    private static QueryWrapper<ServiceOrder> createHomeSettlementQueryWrapper(ServiceOrderDTO query) {
        QueryWrapper<ServiceOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ServiceOrder::getIsDeleted, BusinessConstant.DELETE_NO)
                .in(ServiceOrder::getBelongSystem, MenuAffiliationEnum.P_COMPOSITE_COURT.getCode(), MenuAffiliationEnum.P_COMPOSITE_PRODUCER.getCode())
                .in(ServiceOrder::getOrderSource, ServiceOrderOrderSourceEnum.HOME_BUILDER_REPAIR_ORDER)
                .ne(ServiceOrder::getOrderStatus, ServiceOrderOrderStatusEnum.NOT_SUBMIT)
                .ne(ServiceOrder::getOrderStatus, ServiceOrderOrderStatusEnum.CANCEL)
                .eq(query.getExhibitionManageId() != null, ServiceOrder::getExhibitionManageId, query.getExhibitionManageId())
                .eq(query.getCompanyId() != null, ServiceOrder::getCompanyId, query.getCompanyId())
                .in(query.getCompanyIdList() != null && !query.getCompanyIdList().isEmpty(), ServiceOrder::getCompanyId, query.getCompanyIdList())
                .in(query.getSpaceCodeList() != null && !query.getSpaceCodeList().isEmpty(), ServiceOrder::getSpaceCode, query.getSpaceCodeList())
                .eq(StrUtil.isNotBlank(query.getSpaceCode()), ServiceOrder::getSpaceCode, query.getSpaceCode())
                .eq(StrUtil.isNotBlank(query.getSpaceName()), ServiceOrder::getSpaceName, query.getSpaceName())
                .eq(StrUtil.isNotBlank(query.getSiteName()), ServiceOrder::getSiteName, query.getSiteName())
        ;
        return queryWrapper;
    }
}